﻿using McProtocol.Mitsubishi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ETC.DLEDLightingSystemPlus.Helpers
{
    public class MelsecPLCHelper
    {
        private McProtocolTcp mcProtocol = null;
        public bool IsOpen = false;
        public MelsecPLCHelper(string ip, int port)
        {
            mcProtocol = new McProtocolTcp(ip, port, McFrame.MC3E);
        }
        /// <summary>
        /// PLC连接
        /// </summary>
        /// <returns></returns>
        public async Task<int> Open()
        {
            try
            {
                return await mcProtocol.Open();

            }
            catch (Exception)
            {
                return -1;
            }
        }
        /// <summary>
        /// PLC连接失败
        /// </summary>
        /// <returns></returns>
        public int Close()
        {
            IsOpen = false;
            return mcProtocol.Close();
        }
        /// <summary>
        /// 位元件获取
        /// </summary>
        /// <param name="addressName">位元件名称,Ex：M1</param>
        /// <param name="data">获取软元件的值</param>
        /// <returns></returns>
        public async Task<int[]> GetBitValue(string addressName, int length)
        {
            try
            {
                return await mcProtocol.GetBitDevice(addressName, length);
            }
            catch (Exception)
            {

                return null;
            }

        }
        /// <summary>
        /// 位元件设置
        /// </summary>
        /// <param name="addressName">位元件名称</param>
        /// <param name="data">位元件的值,EX：0 or 1</param>
        /// <returns></returns>
        private async Task<int> SetBitValue(string addressName, int data)
        {
            try
            {

                await mcProtocol.SetBitDevice(addressName, data);
                return 0;


            }
            catch (Exception)
            {
                return -1;
            }
        }
        /// <summary>
        /// 位元件组获取
        /// </summary>
        /// <param name="addressName">位元件起始编号</param>
        /// <param name="data">需设置值的值组</param>
        /// <returns></returns>
        public async Task<int[]> GetBitValues(string addressName, int length)
        {
            return await mcProtocol.GetBitDevice(addressName, length);
        }
        /// <summary>
        /// 设置位元件数组
        /// </summary>
        /// <param name="addressName"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<int> SetBitValues(string addressName, int[] data)
        {
            try
            {
                await mcProtocol.SetBitDevice(addressName, data);
                return IsOpen ? 0 : -2;
            }
            catch (Exception)
            {
                return -1;
            }
        }
        /// <summary>
        /// 获取字元件数组
        /// </summary>
        /// <param name="aAddress"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public async Task<int[]> GetBlockValue(string address, int length)
        {

            try
            {
                return await mcProtocol.ReadDeviceBlock(address, length);
            }
            catch (Exception)
            {

                return null;
            }
        }
        /// <summary>
        ///  设置字元件数组
        /// </summary>
        /// <param name="aAddress"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<int> SetBlockValue(string address, Int32[] data)
        {
            try
            {
                return await mcProtocol.WriteDeviceBlock(address, data.Length, data);
            }
            catch (Exception)
            {
                return -1;
            }

        }
        /// <summary>
        /// 设置文本
        /// </summary>
        /// <param name="address"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<int> SetString(string address, string data)
        {

            byte[] bt = Encoding.UTF8.GetBytes(data);
            int[] ints = new int[bt.Length];
            for (int i = 0; i < bt.Length; i++)
            {
                ints[i] = (int)bt[i];
            }
            return await SetBlockValue(address, ints);


        }
        /// <summary>
        /// 获取文本
        /// </summary>
        /// <param name="address"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public async Task<string> GetString(string address, int length)
        {
            int[] ints = new int[length];
            ints = await GetBlockValue(address, length);
            if (ints == null)
            {
                return null;
            }
            byte[] byteArray = Array.ConvertAll(ints, i => (byte)i);

            return System.Text.Encoding.UTF8.GetString(byteArray);


        }
        /// <summary>
        /// 设置双字数值
        /// </summary>
        /// <param name="address"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<int> SetBlockValue2(string address, Int32[] data)
        {
            List<int> ints = new List<int>();
            foreach (int item in data)
            {
                int high16 = (item >> 16) & 0xFFFF;  // 高16位  
                int low16 = item & 0xFFFF;  // 低16位
                ints.Add(low16);
                ints.Add(high16);
            }
            return await SetBlockValue(address, ints.ToArray());
        }
        /// <summary>
        /// 获取双字数值
        /// </summary>
        /// <param name="address"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public async Task<double[]> GetBlockValue2(string address, int length)
        {
            return PLC_PC(await GetBlockValue(address, length)).ToArray();
        }
        /// <summary>
        /// 32位转16位
        /// </summary>
        /// <param name="LS"></param>
        /// <returns></returns>
        private static List<double> PLC_PC(int[] LS)
        {
            if (LS == null)
            {
                return null;
            }
            List<double> AxisList = new List<double>();

            for (int i = 0; i < LS.Length;)
            {
                int dest = 0;
                short SourceA = (short)LS[i], SourceB = (short)LS[i + 1];//A代表低位，B代表高位
                dest |= SourceB & 0x0000ffff;
                dest = (dest << 16) | (SourceA & 0x0000ffff);

                AxisList.Add(dest);
                i = i + 2;
            }
            return AxisList;
        }
    }


}
